#include "mainwindow.h"
#include <QDebug>
#include <QUuid>
#include <QTimerEvent>
#include <QDomDocument>
#include <QDir>
#include <QFile>
#include <QMenu>
#include <QStatusBar>
#include <QRadioButton>
#include <QButtonGroup>
#include <QDateTime>
#include <QSettings>
#include <QMessageBox>
#include <QPropertyAnimation>
#include <QFileDialog>
#include <QtMath>

#include "HRibbonBar.h"
#include "HRibbonCategory.h"
#include "HRibbonPannel.h"
#include "HRibbonToolButton.h"
#include "HRibbonMenu.h"
#include "HRibbonComboBox.h"
#include "HRibbonLineEdit.h"
#include "HRibbonGallery.h"
#include "HRibbonCheckBox.h"
#include "HRibbonQuickAccessBar.h"
#include "HRibbonButtonGroupWidget.h"
#include "HRibbonApplicationButton.h"
#include "HRibbonCustomizeWidget.h"
#include "HRibbonCustomizeDialog.h"
#include "HFramelessHelper.h"
#include "HRibbonStackedWidget.h"
#include "HRibbonTabBar.h"


MainWindow::MainWindow(QWidget *parent)
    : HRibbonMainWindow(parent)
{
    this->setWindowTitle(tr("HToolBox"));
    this->setObjectName("MainWindow");
    this->resize(1024,768);

    // 中心窗口
    mpCenterWidget = new HRibbonStackedWidget(this);
    mpCenterWidget->setObjectName("CenterWidgetObjectName");
    mpCenterWidget->setAutoResize(true);
    this->setCentralWidget(mpCenterWidget);

    mpDockCenterWidget = new HRibbonStackedWidget(this);
    mpDockCenterWidget->setObjectName("DockCenterWidgetObjectName");
    mpDockCenterWidget->setWindowTitle(tr("FrameDockWidget"));
    mpDockCenterWidget->setAutoResize(true);
    QDockWidget* pdock = new QDockWidget(this);
    pdock->setWidget(mpDockCenterWidget);
    pdock->setAllowedAreas(Qt::RightDockWidgetArea);
    pdock->setFeatures(QDockWidget::DockWidgetClosable);
    pdock->setMinimumWidth(300);
    pdock->setWindowTitle(mpDockCenterWidget->windowTitle());
    this->addDockWidget(Qt::RightDockWidgetArea,pdock);
    pdock->setVisible(false);

    loadMenuConfig();
    initTitleBar();
    loadPlugins();

    startTimer(500);

}

MainWindow::~MainWindow()
{
    delete mpCenterWidget;
    mpCenterWidget = nullptr;
}


void MainWindow::initTitleBar()
{
    ribbonBar()->setRibbonStyle(HRibbonBar::WpsLiteStyleTwoRow);
    setRibbonTheme(HRibbonMainWindow::Office2013);

    HFramelessHelper *helper = framelessHelper();

    helper->setRubberBandOnResize(false);
    setStatusBar(new QStatusBar());
    HRibbonBar *ribbon = ribbonBar();

#if 1
    // 系统菜单，左上角位置
    QAbstractButton* pButton = ribbonBar()->applicationButton();
    pButton->setText(tr("File"));
    QPushButton* pPushButton = dynamic_cast<QPushButton*>(pButton);
    QMenu * pAppMenu = new QMenu(this);
    pPushButton->setMenu(pAppMenu);

    // 系统打开，保存等，保存的信息为系统暂存状态信息
    QAction* paction = new QAction(QIcon(":/icon/New-hover.png"),tr("New Project"),this);
    paction->setObjectName("New Task");
    connect(paction,SIGNAL(triggered()),this,SLOT(slot_newProject()));
    pAppMenu->addAction(paction);

    paction = new QAction(QIcon(":/icon/open.png"),tr("Load Project"),this);
    paction->setObjectName("Load Task");
    connect(paction,SIGNAL(triggered()),this,SLOT(slot_loadProject()));
    pAppMenu->addAction(paction);

    paction = new QAction(QIcon(":/icon/save.png"),tr("Export Project"),this);
    paction->setObjectName("Export Project");
    connect(paction,SIGNAL(triggered()),this,SLOT(slot_exportProject()));
    pAppMenu->addAction(paction);

    paction = new QAction(QIcon(":/icon/saveas.png"),tr("SaveAs Project"),this);
    paction->setObjectName("SaveAs Project");
    connect(paction,SIGNAL(triggered()),this,SLOT(slot_saveAsProject()));
    pAppMenu->addAction(paction);

    paction = new QAction(QIcon(":/icon/tools.png"),tr("Setting"),this);
    paction->setObjectName("SystemConfigActionObjectName");
    connect(paction,SIGNAL(triggered()),this,SLOT(slot_SystemConfigActionTriggered()));
    pAppMenu->addAction(paction);

    paction = new QAction(QIcon(":/icon/Exit.png"),tr("Exit"),this);
    paction->setObjectName("Exit Application");
    connect(paction,SIGNAL(triggered()),this,SLOT(slot_exit()));
    pAppMenu->addAction(paction);

#endif

#ifdef DEVELOP
    QButtonGroup *g = new QButtonGroup(this);
    QRadioButton *r = new QRadioButton();
    r->setObjectName(("use office style"));
    r->setText(tr("OfficeNormal"));
    r->setChecked(false);
    g->addButton(r, HRibbonBar::OfficeStyle);
    addSmallWidget("xitongguanli","caidanfengge",r);

    r = new QRadioButton();
    r->setObjectName(("use wps style"));
    r->setText(tr("WPSNormal"));
    r->setChecked(false);
    g->addButton(r, HRibbonBar::WpsLiteStyle);
    addSmallWidget("xitongguanli","caidanfengge",r);

    r = new QRadioButton();
    r->setObjectName(("use office 2row style"));
    r->setText(tr("OfficeLite"));
    r->setChecked(false);
    g->addButton(r, HRibbonBar::OfficeStyleTwoRow);
    addSmallWidget("xitongguanli","caidanfengge",r);

    r = new QRadioButton();
    r->setObjectName(("use wps 2row style"));
    r->setText(tr("WPSLite"));
    r->setChecked(true);
    g->addButton(r, HRibbonBar::WpsLiteStyleTwoRow);
    addSmallWidget("xitongguanli","caidanfengge",r);


#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    connect(g, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::idClicked), this, &MainWindow::onStyleClicked);
#else
    connect(g, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &MainWindow::onStyleClicked);
#endif

#endif // unused

    HRibbonQuickAccessBar *quickAccessBar = ribbon->quickAccessBar();

    mpTimeLabel = new QLabel(this);
    QFont f = QFont("Microsoft YaHei");
    f.setBold(true);
    mpTimeLabel->setFont(f);
    mpTimeLabel->setText(tr("BT:")+QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
    quickAccessBar->addWidget(mpTimeLabel);

    QAction* act = new QAction(this);
    act->setObjectName(("hide ribbon"));
    act->setIcon(QIcon(":/icon/ribbonMinimize.png"));
    act->setProperty("State","MAX");
    act->setText(tr("hide ribbon"));
    connect(act, SIGNAL(triggered(bool)),this,SLOT(slot_minMaxRibbonBar(bool)));
    quickAccessBar->addAction(act);

    QAction* actVoice = new QAction(this);
    actVoice->setObjectName(("showhide voice"));
    actVoice->setIcon(QIcon(":/icon/micro.png"));
    actVoice->setText(tr("hide voice"));
    actVoice->setCheckable(true);
    actVoice->setChecked(false);
    connect(actVoice, SIGNAL(triggered(bool)),this,SLOT(slot_minMaxVoicePan(bool)));
    quickAccessBar->addAction(actVoice);

    //    quickAccessBar->addAction(new QAction(QIcon(":/icon/bar.png"), "action1", this));
    //    quickAccessBar->addAction(new QAction(QIcon(":/icon/curve.png"), "action2", this));
    //    quickAccessBar->addSeparator();
    //    quickAccessBar->addAction(new QAction(QIcon(":/icon/icon2.png"), "action3", this));
    //    quickAccessBar->addAction(new QAction(QIcon(":/icon/polyline.png"), "action3", this));

#ifdef DEVELOP
    // 支持快速创建一个bundle
    paction = new QAction(QIcon(":/icon/bundle.png"),tr("CreatBundleTool"),this);
    paction->setObjectName("CreatBundleToolActionObjectName");
    connect(paction,SIGNAL(triggered(bool)),this,SLOT(slot_generateBundle()));
    addFrameAction("xitongguanli","chajianguanli",paction,3);

    paction = new QAction(QIcon(":/icon/bundle.png"),tr("IconTranslate"),this);
    paction->setObjectName("IconTranslateToolActionObjectName");
    connect(paction,SIGNAL(triggered(bool)),this,SLOT(slot_IconTranslate()));
    addFrameAction("xitongguanli","chajianguanli",paction,3);
#endif

#if 0
    paction = new QAction(QIcon(":/icon/wizard.png"),tr("CreatDataTool"),this);
    paction->setObjectName("CreatDataToolActionObjectName");
    connect(paction,SIGNAL(triggered(bool)),this,SLOT(slot_generateData(bool)));
    addFrameAction("xitongguanli","chajianguanli",paction,3);
#endif

#ifdef DEVELOP
    // 添加帮助按钮
    // 配置、帮助、退出等
    paction = new QAction(QIcon(":/icon/Help-click.png"),tr("Help"),this);
    paction->setObjectName("HelpAction");
    //    connect(paction,SIGNAL(triggered(bool)),this,SLOT(slot_generateData(bool)));
    addFrameAction(QString("xitongguanli"),QString("peizhiguanli"),paction,1);

    paction = new QAction(QIcon(":/icon/Exit.png"),tr("Exit"),this);
    paction->setObjectName("ExitAction");
    //    connect(paction,SIGNAL(triggered(bool)),this,SLOT(slot_generateData(bool)));
    addFrameAction(QString("xitongguanli"),QString("peizhiguanli"),paction,1);
#endif
}

void MainWindow::loadMenuConfig()
{
    QDir dir(QCoreApplication::applicationDirPath());
    dir.cdUp();
    dir.cd("config");
    QFile file(dir.absoluteFilePath("menuconfig.xml"));
    if(!file.open(QIODevice::ReadOnly))return;
    QDomDocument doc;
    doc.setContent(&file);
    file.close();

    QDomElement hroot = doc.firstChildElement("hroot");
    if(hroot.isNull())return;
    QDomElement category = hroot.firstChildElement("category");
    while (!category.isNull()) {
        HRibbonCategory* page = ribbonBar()->addCategoryPage(category.attribute("ch"));
        page->setObjectName(category.attribute("en"));

        QDomElement pannel = category.firstChildElement("pannel");
        while (!pannel.isNull()) {
            HRibbonPannel* group = page->addPannel(pannel.attribute("ch"));
            group->setObjectName(pannel.attribute("en"));
            pannel = pannel.nextSiblingElement("pannel");
        }

        category = category.nextSiblingElement("category");
    }

}

void MainWindow::loadPlugins()
{
    m_loadedPlugins.clear();
    m_framework = m_frameWorkFactory.getFramework();
    try
    {
        // 初始化并启动插件框架
        m_framework->init();
        m_framework->start();
        qDebug() << "Plugin Framework start ...";
    }
    catch (const BundleException &e)
    {
        qDebug() << "Failed to initialize the Bundle framework: " << e.what();
        return;
    }
    qDebug()<<"init framework";
    // 初始化并启动插件框架
    IBundleContext* context = m_framework->getPluginContext();
#if 1
    context->registerService<IMainFrameService>(this);

    QDir dir(QString("%1/plugins").arg(qApp->applicationDirPath()));
    if(!dir.exists()){
        dir.mkdir(QString("%1/plugins").arg(qApp->applicationDirPath()));
        dir.setPath(QString("%1/plugins").arg(qApp->applicationDirPath()));
    }
    // 注意区分windows和linux，后缀名不同
    QStringList lstFiles = dir.entryList(QDir::Files);
    int fileCount = lstFiles.count();
    while (fileCount--) {
#if WIN32
        if(lstFiles.at(fileCount).right(4) != ".dll")
#else
        if(lstFiles.at(fileCount).right(3) != ".so")
#endif
        {
            lstFiles.removeAt(fileCount);
        }
    }
    //#if WIN32
    //    QVector<QFileInfo> files = dir.entryInfoList(QStringList() << "*.dll").toVector();
    //#else
    //    QVector<QFileInfo> files = dir.entryInfoList(QStringList() << "*.so").toVector();
    //#endif
    //    qDebug() << "PluginsNum: " << files.size();
    for(int i=0; i<lstFiles.count(); ++i)
    {
        QString strPlugin = dir.absoluteFilePath(lstFiles.at(i));
        try
        {
            qDebug()<<strPlugin;
            //            qDebug()<<"pre load bundle"<<strPlugin;
            // 执行install后，plugin的状态为INSTALLED
            QSharedPointer<IBundle> plugin = context->installPlugin(QUrl::fromLocalFile(strPlugin));
            //            qDebug()<<"install plugin"<<strPlugin;
            // 执行start后，plugin状态为ACTIVE
            if(plugin)
            {
                // 设置插件的启动模式从manifest.mf文件中读取
                //plugin->start(Bundle::START_TRANSIENT);   // 插件立即启动
                //                qDebug()<<"bundle starting";
                plugin->start(IBundle::START_ACTIVATION_POLICY);

                // 获取插件的状态
                IBundle::State startState = plugin.data()->getState();
                if(IBundle::ACTIVE == startState)
                {
                    // 即时启动模式
                    m_pluginsLoaded.push_back(qMakePair(strPlugin, true));
                    qDebug() << tr("installed plugin_%1 :%2").arg(i + 1).arg(strPlugin);
                }
                else if(IBundle::STARTING == startState)
                {
                    // 延时启动模式
                    m_pluginsLoaded.push_back(qMakePair(strPlugin, false));
                    qDebug() << tr("lazy install plugin_%1 :%2").arg(i + 1).arg(strPlugin);
                }

                m_loadedPlugins.append(plugin);
            }
        }
        catch(BundleException &e)
        {
            QMessageBox::warning(this, tr("Warning"), tr("failed to load plugin %1").arg(strPlugin));
            continue;
        }
    }
#endif
}

void MainWindow::addFrameAction(const QString &pageName, const QString &groupName, QAction *action,int mode)
{
    HRibbonCategory* page = ribbonBar()->categoryByObjectName(pageName);
    if(nullptr == page){
        page = ribbonBar()->addCategoryPage(pageName);
        page->setObjectName(pageName);
    }

    HRibbonPannel* pgroup = page->pannelByObjectName(groupName);
    if(nullptr == pgroup){
        pgroup = page->addPannel(groupName);
        pgroup->setObjectName(pageName);
    }

    if(mode == 1)
    {
        pgroup->addLargeAction(action);
    }
    else if(mode == 2)
    {
        pgroup->addMediumAction(action);
    }
    else if(mode == 3)
    {
        pgroup->addSmallAction(action);
    }
    else
    {
        return;
    }
}

void MainWindow::addSmallWidget(const QString &pageName, const QString &groupName, QWidget *widget)
{
    HRibbonCategory* page = ribbonBar()->categoryByObjectName(pageName);
    if(nullptr == page){
        page = ribbonBar()->addCategoryPage(pageName);
        page->setObjectName(pageName);
        return;
    }

    HRibbonPannel* pgroup = page->pannelByObjectName(groupName);
    if(nullptr == pgroup){
        pgroup = page->addPannel(groupName);
        pgroup->setObjectName(pageName);
        return;
    }

    pgroup->addSmallWidget(widget);
}

void MainWindow::removeFrameAction(const QString &pageName, const QString &groupName,QAction *action)
{
    HRibbonCategory* page = ribbonBar()->categoryByObjectName(pageName);
    if(nullptr == page){
        qWarning()<<"remove action failed,page is not exist"<<pageName;
        return;
    }

    HRibbonPannel* pgroup = page->pannelByObjectName(groupName);
    if(nullptr == pgroup){
        qWarning()<<"remove action failed,group is not exist"<<groupName;
        return;
    }

    pgroup->removeAction(action);
    if(pgroup->actions().count() == 0)
    {
        //        qDebug()<<"remove group"<<groupName;
        page->removePannel(pgroup);
    }

    if(page->pannelCount() == 0)
    {
        //        qDebug()<<"remove page"<<pageName;
        ribbonBar()->removeCategory(page);
    }
}

void MainWindow::addActionPage(const QString &pageName)
{
    HRibbonCategory* page = ribbonBar()->categoryByObjectName(pageName);
    if(nullptr == page){
        page = ribbonBar()->addCategoryPage(pageName);
        return;
    }
}

void MainWindow::removeActionPage(const QString &pageName)
{
    HRibbonCategory* page = ribbonBar()->categoryByObjectName(pageName);
    if(nullptr == page){
        qWarning()<<"remove group failed,page is note exist"<<pageName;
        return;
    }
    else
    {
        ribbonBar()->removeCategory(page);
    }
}

void MainWindow::addActionGroup(const QString &pageName, const QString &groupName)
{
    HRibbonCategory* page = ribbonBar()->categoryByObjectName(pageName);
    if(nullptr == page){
        page = ribbonBar()->addCategoryPage(pageName);
    }

    if(page->pannelByObjectName(groupName) == nullptr)
    {
        page->addPannel(groupName);
    }
}

void MainWindow::removeActionGroup(const QString &pageName, const QString &groupName)
{
    HRibbonCategory* page = ribbonBar()->categoryByObjectName(pageName);
    if(nullptr == page){
        qWarning()<<"remove group failed,page is not exist"<<pageName;
        return;
    }

    HRibbonPannel* pgroup = page->pannelByObjectName(groupName);
    if(!page->removePannel(pgroup))
    {
        qWarning()<<"remove group failed,group is not exist"<<groupName;
    }
}

void MainWindow::removeFrameCenterWidget(QWidget *widget)
{
    //    qDebug()<<"frame remove centerwidget"<<widget->objectName();
    if(nullptr == widget || widget->objectName().isEmpty())
    {
        qWarning()<<"failed remove widget"<<widget->objectName();
        return;
    }
    mpCenterWidget->removeWidget(widget);

    return;
}

QDockWidget* MainWindow::addFrameDockWidget(QWidget *widget,Qt::DockWidgetArea area)
{
    if(widget == nullptr)return nullptr;

    QDockWidget* pdock = new QDockWidget(this);
    pdock->setWidget(widget);
    pdock->setWindowTitle(widget->windowTitle());
    this->addDockWidget(area,pdock);
    return pdock;
}

int MainWindow::addFrameDockCenterWidget(QWidget *widget)
{
    if(nullptr == mpDockCenterWidget)return -1;
    if(nullptr == widget)return -1;
    if(widget->objectName().isEmpty())
        widget->setObjectName(QString("widget%1").arg(QUuid::createUuid().toString()));
    if(widget->windowTitle().isEmpty())
        widget->setWindowTitle(tr("UnNamedWidget"));

    int index = 0;
    index = mpDockCenterWidget->addWidget(widget);

    return index;
}

IDataManager* MainWindow::getDataManager()
{
    return nullptr;
}

void MainWindow::timerEvent(QTimerEvent *event)
{
    mpTimeLabel->setText(tr("BT:")+QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
    QMainWindow::timerEvent(event);
}

int MainWindow::addFrameCenterWidget(QWidget *widget)
{
    if(widget->objectName().isEmpty())
        widget->setObjectName(QString("widget%1").arg(QUuid::createUuid().toString()));
    if(widget->windowTitle().isEmpty())
        widget->setWindowTitle(tr("UnNamedWidget"));

    int index = 0;
    index = mpCenterWidget->addWidget(widget);

    return index;
}

QStackedWidget *MainWindow::getCenterWidget()
{
    return mpCenterWidget;
}

QMainWindow *MainWindow::getBaseWindow()
{
    return this;
}

void MainWindow::slot_minMaxRibbonBar(bool a)
{
    Q_UNUSED(a)
    QAction* act = dynamic_cast<QAction*>(sender());

    if(nullptr == act)
        return;

    if(act->property("State").toString() == "MIN")
    {
        act->setProperty("State","MAX");
        act->setIcon(QIcon(":/icon/ribbonMinimize.png"));
        act->setText(tr("hide ribbon"));
        this->ribbonBar()->setMinimumMode(false);
    }
    else
    {
        act->setProperty("State","MIN");
        act->setIcon(QIcon(":/icon/ribbonMaximize.png"));
        act->setText(tr("show ribbon"));
        this->ribbonBar()->setMinimumMode(true);
    }
}

void MainWindow::slot_minMaxVoicePan(bool b)
{
    QAction* act = dynamic_cast<QAction*>(sender());
    if(nullptr == act)return;
    if(b){
        mpVoiceWidgteAnimation->setEndValue(QRect(0, 620, 270, 400)); // 抽屉滑入位置
    }
    else{
        mpVoiceWidgteAnimation->setEndValue(QRect(-270, 620, 270, 400)); // 抽屉滑出位置
    }
    mpVoiceWidgteAnimation->start();
}

void MainWindow::slot_showCentralView(bool)
{
    QObject* p = sender();

    //    qDebug()<<p->objectName()<<mpCenterWidget->count();
    for(int i=0; i<mpCenterWidget->count(); ++i)
    {
        if(p->objectName().section("widact:",1,1) == mpCenterWidget->widget(i)->objectName())
        {
            mpCenterWidget->setCurrentIndex(i);
            //            qDebug()<<"showcurrentview"<<mpCenterWidget->widget(i)->objectName();

            return;
        }
    }

}

void MainWindow::onStyleClicked(int id)
{
    ribbonBar()->setRibbonStyle(static_cast<HRibbonBar::RibbonStyle>(id));
}


#include "bundledesignerdialog.h"
void MainWindow::slot_generateBundle()
{
    BundleDesignerDialog dlg(this);
    dlg.exec();
}

#include "icondesigndialog.h"
void MainWindow::slot_IconTranslate()
{
    IconDesignDialog dlg(this);
    dlg.exec();
}

void MainWindow::slot_exit()
{
    exit(0);
    //    this->close();
}

void MainWindow::slot_newProject()
{

}

void MainWindow::slot_loadProject()
{

}

void MainWindow::slot_exportProject()
{

}

void MainWindow::slot_saveAsProject()
{

}

void MainWindow::slot_SystemConfigActionTriggered()
{

}



